home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / telecom / 107 / c / readpic.c < prev    next >
Encoding:
Text File  |  1987-02-20  |  11.6 KB  |  411 lines

  1. /*
  2.     General purpose ST pic file reader source code.
  3.     Reads Neo, DEGAS, DEGAS compressed, & Tiny formats.
  4.     This code is public domain.  Written by John Brochu.
  5.     Set tabs to 4 for best results.
  6.  
  7.     To use, you must set up a screen buffer (32000 bytes)
  8.     (or use the current system screen address to read the pic
  9.     directly into screen memory), palette buffer (16 ints),
  10.     and a resolution flag (1 int).
  11.  
  12.     The pic is read into a temporary buffer, unpacked if needed,
  13.     and moved to the proper buffers.  You may then display the pic
  14.     by using the appropriate bios calls to set the resolution/palette/
  15.     screen address.  If you use a pic buffer rather than screen memory,
  16.     be sure the buffer is on a 256-byte boundary!
  17.  
  18.     My source to compress a pic to DEGAS compressed format is also included.
  19.  */
  20.  
  21. /*    Globals        */
  22. char    tmp_buf[32000],        /* Temp buffer where file is read in    */
  23.         *iff_in, *iff_out;    /* Pointers for DEGAS unpack() routine    */
  24.  
  25. /*---------------------------------------------------------------------------*/
  26. /*                    |--------- DEGAS ---------|            */
  27. /*                     UNCOMPRESSED   COMPRESSED            */
  28. /*               NEO   low med mono  low med mono     TINY    */
  29. /*    typ...        0     1   2   3     4   5   6     7        */
  30. /* Returns length of file or (neg) error code.            */
  31.  
  32. long    load_pic(fil_nam, pic_adr, pic_pal, pic_rez, typ)
  33. char    *fil_nam;        /* Pointer to filename            */
  34. long    pic_adr;        /* Addr of pic buffer            */
  35. int        *pic_pal;        /* Pointer to palette buffer    */
  36. int        *pic_rez;        /* Pointer to res variable        */
  37. int        typ;            /* Pic type (see above)            */
  38. {
  39.     char    buf[130],    /* Temp storage for file header        */
  40.             *p;
  41.     int        x,
  42.             hndl,        /* File handle                        */
  43.             retry_flg,    /* Allows a retry on file error (not used)    */
  44.             pal_ofs,    /* Offset into file to palette        */
  45.             ctl_ofs,    /* Offset to control segment (Tiny)    */
  46.             dat_ofs,    /* Offset to data segment (Tiny)    */
  47.             ctrl_len,    /* Length of control segment (Tiny)    */
  48.             data_len,    /* Length of data segment (Tiny)    */
  49.             lines;        /* #lines in pic                    */
  50.     long    length,        /* Length of file read in            */
  51.             hdr_len,    /* Length of file header (non-data)    */
  52.             ctl_in,        /* Addr of Tiny control segment        */
  53.             dat_in;        /* Addr of Tiny data segment        */
  54.  
  55.     do {
  56.         retry_flg = 0;
  57.         graf_mouse(HOURGLASS, 0L);
  58.         length = Fopen(fil_nam, 0);
  59.         if (length < 0)        /* File not found    */
  60.             continue;
  61.         hndl = length;        /* Otherwise file handle was returned    */
  62.         if (typ==0) {            /* NeoChrome (0) */
  63.             hdr_len = 128L;
  64.             pal_ofs = 4;
  65.         } else if (typ < 7) {    /* DEGAS (1-6) */
  66.             hdr_len = 34L;
  67.             pal_ofs = 2;
  68.         } else {                /* Tiny (7) */
  69.             hdr_len = 37L;        /* (assume no color rotation info for now)    */
  70.             pal_ofs = 1;
  71.             ctl_ofs = 33;
  72.             dat_ofs = 35;
  73.         }
  74.         length = Fread(hndl, hdr_len, buf);    /* Read header */
  75.         if (length < 0)            /* Error, abort (critical error)    */
  76.             retry_flg = 0;
  77.         else {                    /* All's well, process the file...    */
  78.             if (typ==7)            /* Check pic res... */
  79.                 x = buf[0] & 7;        /* Mask Tiny rotation flag        */
  80.             else {
  81.                 p = &x;                /* Get res in x                    */
  82.                 *p++ = buf[pal_ofs-2];
  83.                 *p++ = buf[pal_ofs-1];
  84.             }
  85.             if (((typ>0)&&(typ<7)) && (x & 0x8000)) {    /* DEGAS compr. flag */
  86.                 typ = (x & 3) + 4;
  87.                 x &= 0x7fff;
  88.             }
  89.             if ((typ==7) && (x > 2)) {        /* Tiny rotation flag */
  90.                 length = Fread(hndl, 4L, &buf[hdr_len]);    /* Read the xtra */
  91.                 if (length < 0) {            /* Error, abort (critical error) */
  92.                     retry_flg = 0;
  93.                     continue;
  94.                 }
  95.                 x -= 3;            /* Mask off the rotation flag    */
  96.                 pal_ofs += 4;    /* Adjust offsets...            */
  97.                 ctl_ofs += 4;
  98.                 dat_ofs += 4;
  99.             }
  100.             if ((x < 0)||(x > 2)) {                    /* Invalid res flag,     */
  101.                 Fclose(hndl);                        /*  assume bad pic file    */
  102.                 graf_mouse(ARROW, 0L);
  103.                 return(-1L);
  104.             }                
  105.             *pic_rez = x;
  106.             for (x=0; x<32; ++x)
  107.                 *(pic_pal+x) = buf[x+pal_ofs];        /* Get palette */
  108.             if (typ < 4) {    /* Read DEGAS, Neo uncompressed screen image... */
  109.                 length = Fread(hndl, 32000L, pic_adr);
  110.                 if (length < 0)   
  111.                     retry_flg = 0;    /* Abort (read error) */
  112.             } else if (typ < 7) {    /* Read and uncompress DEGAS screen... */
  113.                 length = Fread(hndl, 32000L, tmp_buf);
  114.                 if (length < 0)
  115.                     retry_flg = 0;    /* Abort (read error) */
  116.                 else {
  117.                     x = *pic_rez;
  118.                     if (x < 2)    lines = 200;        /* Low, med-res    */
  119.                     else        lines = 400;        /* Monochrome    */
  120.                     iff_in = tmp_buf;
  121.                     iff_out = pic_adr;
  122.                     do        unpack(x);            /* Unpack a line at a time */
  123.                     while (--lines);
  124.                 }
  125.             } else {                    /* Tiny format */
  126.                 /* Note: since Tiny pics always have an odd # of header bytes,
  127.                     we read starting at an odd addr to speed things up.    */
  128.                 length = Fread(hndl, 32000L, tmp_buf+1);
  129.                 if (length < 0)
  130.                     retry_flg = 0;    /* Abort (read error) */
  131.                 else {
  132.                     p = &ctrl_len;                /* Get control length...*/
  133.                     *p++ = buf[ctl_ofs];
  134.                     *p++ = buf[ctl_ofs+1];
  135.                     p = &data_len;                /* Get data length...    */
  136.                     *p++ = buf[dat_ofs];
  137.                     *p++ = buf[dat_ofs+1];
  138.                     ctl_in = tmp_buf + 1;        /* Addr of control segment,    */
  139.                     dat_in = tmp_buf + 1 + ctrl_len;    /*    data segment    */
  140.                     untiny(ctl_in, dat_in, pic_adr, ctrl_len);
  141.                 }
  142.             }
  143.         }
  144.         Fclose(hndl);
  145.     } while (retry_flg);
  146.     graf_mouse(ARROW, 0L);
  147.     return(length);
  148. }
  149.  
  150. /*---------------------------------------------------------------------------*/
  151.  
  152. /* Unpacks a single scan line & updates iff_in & iff_out global pointers
  153.  
  154.                      /    byt ==  0 to  127  copy next [byt+1] bytes
  155. Unpack routine --if-<    byt == -1 to -127  copy next byte [-byt+1] times
  156.                      \    byt == 128         NO-OP                            */
  157.  
  158. unpack(rez)
  159. int    rez;
  160. {
  161.     register char    *src_ptr, *dst_ptr, byt, cnt;
  162.     register int    minus128 = -128, len;
  163.     char            linbuf[320];        /* Oversize just in case! */
  164.     int                llen;
  165.  
  166.  
  167.     if (rez < 2)    len = 160;
  168.     else            len = 80;
  169.     llen = len;
  170.     src_ptr = iff_in;
  171.     dst_ptr = &linbuf[0];
  172.  
  173.     while (len > 0) {
  174.         byt = *src_ptr++;
  175.         if (byt >= 0) {
  176.             ++byt;
  177.             do {
  178.                 *dst_ptr++ = *src_ptr++;
  179.                 --len;
  180.             } while (--byt);
  181.         }
  182.         else if (byt != minus128) {
  183.             cnt = -byt + 1;
  184.             byt = *src_ptr++;
  185.             do {
  186.                 *dst_ptr++ = byt;
  187.                 --len;
  188.             } while (--cnt);
  189.         }
  190.     }
  191.     ilbm_st(linbuf, iff_out, rez);
  192.     iff_in = src_ptr;                    /* Update global pointers */
  193.     iff_out += llen;
  194. }
  195.  
  196. /*---------------------------------------------------------------------------*/
  197.  
  198. ilbm_st(src_ptr, dst_ptr, rez)        /* Convert ILBM format line to ST format */
  199. int        *src_ptr, *dst_ptr, rez;
  200. {
  201.     int        x, *p0_ptr, *p1_ptr, *p2_ptr, *p3_ptr;
  202.  
  203.     if (rez==0) {                /* Low-res */
  204.         p0_ptr = src_ptr;
  205.         p1_ptr = src_ptr + 20;
  206.         p2_ptr = src_ptr + 40;
  207.         p3_ptr = src_ptr + 60;
  208.         for (x=0; x<20; ++x) {
  209.             *dst_ptr++ = *p0_ptr++;
  210.             *dst_ptr++ = *p1_ptr++;
  211.             *dst_ptr++ = *p2_ptr++;
  212.             *dst_ptr++ = *p3_ptr++;
  213.         }
  214.     } else if (rez==1) {        /* Med-res */
  215.         p0_ptr = src_ptr;
  216.         p1_ptr = src_ptr + 40;
  217.         for (x=0; x<40; ++x) {
  218.             *dst_ptr++ = *p0_ptr++;
  219.             *dst_ptr++ = *p1_ptr++;
  220.         }
  221.     } else {                    /* Monochrome */
  222.         for (x=0; x<40; ++x)
  223.             *dst_ptr++ = *src_ptr++;
  224.     }
  225. }
  226.  
  227. /*---------------------------------------------------------------------------
  228.     Unpacks a single scan line & updates iff_in & iff_out global pointers
  229.  
  230.                      /    byt ==  0 to  127  copy next [byt+1] bytes
  231. Unpack routine --if-<    byt == -1 to -127  copy next byte [-byt+1] times
  232.                      \    byt == 128         NO-OP
  233. */
  234.  
  235. unpack(rez)
  236. int    rez;
  237. {
  238.     register char    *src_ptr, *dst_ptr, byt, cnt;
  239.     register int    minus128 = -128, len;
  240.     char            linbuf[200];
  241.     int                llen;
  242.  
  243.  
  244.     if (rez < 2)    len = 160;
  245.     else            len = 80;
  246.     llen = len;
  247.     src_ptr = iff_in;
  248.     dst_ptr = &linbuf[0];
  249.  
  250.     while (len > 0) {
  251.         byt = *src_ptr++;
  252.         if (byt >= 0) {
  253.             ++byt;
  254.             do {
  255.                 *dst_ptr++ = *src_ptr++;
  256.                 --len;
  257.             } while (--byt);
  258.         }
  259.         else if (byt != minus128) {
  260.             cnt = -byt + 1;
  261.             byt = *src_ptr++;
  262.             do {
  263.                 *dst_ptr++ = byt;
  264.                 --len;
  265.             } while (--cnt);
  266.         }
  267.     }
  268.     ilbm_st(linbuf, iff_out, rez);
  269.     iff_in = src_ptr;                    /* Update global pointers */
  270.     iff_out += llen;
  271. }
  272.  
  273. /*---------------------------------------------------------------------------*/
  274.  
  275. ilbm_st(src_ptr, dst_ptr, rez)        /* Convert ILBM format line to ST format */
  276. int        *src_ptr, *dst_ptr, rez;    /*  (ILBM = InterLeaved BitMap)             */
  277. {
  278.     int        x, *p0_ptr, *p1_ptr, *p2_ptr, *p3_ptr;
  279.  
  280.     if (rez==0) {                /* Low-res */
  281.         p0_ptr = src_ptr;
  282.         p1_ptr = src_ptr + 20;
  283.         p2_ptr = src_ptr + 40;
  284.         p3_ptr = src_ptr + 60;
  285.         for (x=0; x<20; ++x) {
  286.             *dst_ptr++ = *p0_ptr++;
  287.             *dst_ptr++ = *p1_ptr++;
  288.             *dst_ptr++ = *p2_ptr++;
  289.             *dst_ptr++ = *p3_ptr++;
  290.         }
  291.     } else if (rez==1) {        /* Med-res */
  292.         p0_ptr = src_ptr;
  293.         p1_ptr = src_ptr + 40;
  294.         for (x=0; x<40; ++x) {
  295.             *dst_ptr++ = *p0_ptr++;
  296.             *dst_ptr++ = *p1_ptr++;
  297.         }
  298.     } else {                    /* Monochrome */
  299.         for (x=0; x<40; ++x)
  300.             *dst_ptr++ = *src_ptr++;
  301.     }
  302. }
  303.  
  304. /*---------------------------------------------------------------------------*/
  305.  
  306. /* Packs a single scan line & updates iff_in & iff_out global pointers */
  307. /* Returns # of bytes written to output buffer */
  308.  
  309. long    pack()
  310. {
  311.     register char    *src_ptr, *dst_ptr, *run_ptr,
  312.                     c, lastc, repcnt, runcnt, runlen;
  313.     char            linbuf[200];
  314.     int                len, plen, pln;
  315.     long            iff0_out = iff_out;
  316.  
  317.     if (pic_rez == 0) {
  318.         len = 160;
  319.         pln = 4;
  320.     } else if (pic_rez == 1) {
  321.         len = 160;
  322.         pln = 2;
  323.     } else {
  324.         len = 80;
  325.         pln = 1;
  326.     }
  327.     plen = len/pln;        /* Scan length (1 plane) in bytes */
  328.     st_ilbm(iff_in, linbuf, pic_rez);    /* Unweave the planes into ILBM form */
  329.     iff_in += len;                        /* Update global pointer */
  330.     src_ptr = &linbuf[0];
  331.     dst_ptr = iff_out;
  332.  
  333.     for (; pln; --pln) {        /* Pack each scan line's plane separately */
  334.         len = plen - 1;
  335.         run_ptr = src_ptr;
  336.         lastc = *src_ptr++;
  337.         repcnt = runcnt = 1;
  338.  
  339.         for (; len; --len) {
  340.             c = *src_ptr++;                        /* Get next input byte */
  341.             ++runcnt;                            /* Increment run counter */
  342.             if (c == lastc)        ++repcnt;        /* Increment repeat counter */
  343.             else {
  344.                 if (repcnt > 2) {    /* If >2 chars repeated, output the run */
  345.                     runlen = runcnt - repcnt - 1;
  346.                     if (runlen) {        /* Output copy-run if pending... */
  347.                         *dst_ptr++ = runlen - 1;
  348.                         for (; runlen; --runlen)
  349.                             *dst_ptr++ = *run_ptr++;
  350.                     }
  351.                     *dst_ptr++ = (char)1 - repcnt;    /* Output repeat-run... */
  352.                     *dst_ptr++ = lastc;
  353.                     runcnt = 1;                        /* Reset run counter */
  354.                     run_ptr = src_ptr - 1;            /*  & copy-run pointer */
  355.                 }
  356.                 repcnt = 1;
  357.                 lastc = c;
  358.             }
  359.         }
  360.  
  361.         if (repcnt > 2) {                /* End of scan line, finish up... */
  362.             runlen = runcnt - repcnt;
  363.             if (runlen) {        /* Output copy-run if one is pending... */
  364.                 *dst_ptr++ = runlen - 1;
  365.                 for (; runlen; --runlen)
  366.                     *dst_ptr++ = *run_ptr++;
  367.             }
  368.             *dst_ptr++ = (char)1 - repcnt;    /* Output repeat-run... */
  369.             *dst_ptr++ = lastc;
  370.         } else {
  371.             *dst_ptr++ = runcnt - 1;        /* Output copy-run... */
  372.             for (; runcnt; --runcnt)
  373.                 *dst_ptr++ = *run_ptr++;
  374.         }
  375.     }
  376.  
  377.     iff_out = dst_ptr;
  378.     return(iff_out - iff0_out);
  379. }
  380.  
  381. /*---------------------------------------------------------------------------*/
  382.  
  383. st_ilbm(src_ptr, dst_ptr, rez)        /* Convert ST scan line to ILBM format */
  384. int        *src_ptr, *dst_ptr, rez;
  385. {
  386.     int        x, *p0_ptr, *p1_ptr, *p2_ptr, *p3_ptr;
  387.  
  388.     if (rez==0) {                /* Low-res */
  389.         p0_ptr = dst_ptr;
  390.         p1_ptr = dst_ptr + 20;
  391.         p2_ptr = dst_ptr + 40;
  392.         p3_ptr = dst_ptr + 60;
  393.         for (x=0; x<20; ++x) {
  394.             *p0_ptr++ = *src_ptr++;
  395.             *p1_ptr++ = *src_ptr++;
  396.             *p2_ptr++ = *src_ptr++;
  397.             *p3_ptr++ = *src_ptr++;
  398.         }
  399.     } else if (rez==1) {        /* Med-res */
  400.         p0_ptr = dst_ptr;
  401.         p1_ptr = dst_ptr + 40;
  402.         for (x=0; x<40; ++x) {
  403.             *p0_ptr++ = *src_ptr++;
  404.             *p1_ptr++ = *src_ptr++;
  405.         }
  406.     } else {                    /* Monochrome */
  407.         for (x=0; x<40; ++x)
  408.             *dst_ptr++ = *src_ptr++;
  409.     }
  410. }
  411.